home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / program / cpp112.zoo / src / process.c < prev    next >
C/C++ Source or Header  |  1994-07-01  |  6KB  |  219 lines

  1.  
  2. /*---------------------------------------------------------------------*\
  3. |                                    |
  4. | CPP -- a stand-alone C preprocessor                    |
  5. | Copyright (c) 1993 Hacker Ltd.        Author: Scott Bigham    |
  6. |                                    |
  7. | Permission is granted to anyone to use this software for any purpose    |
  8. | on any computer system, and to redistribute it freely, with the    |
  9. | following restrictions:                        |
  10. | - No charge may be made other than reasonable charges for repro-    |
  11. |     duction.                                |
  12. | - Modified versions must be clearly marked as such.            |
  13. | - The author is not responsible for any harmful consequences of    |
  14. |     using this software, even if they result from defects therein.    |
  15. |                                    |
  16. | process.c -- general input processing and output            |
  17. \*---------------------------------------------------------------------*/
  18.  
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include "global.h"
  23.  
  24. struct file_state {
  25.   char *old_curfile;
  26.   char *old_curdir;
  27.   FILE *old_inf;
  28.   unsigned long old_lastline, old_thisline, old_nextline;
  29. };
  30.  
  31. #define MAX_BLANK_LINES 5
  32.  
  33. /*
  34.    sync_line() -- generate a synchronization line of the form "# line-num
  35.    filename", where line-num is determined by |this_line|. Sets |last_line|
  36.    to |this_line|.  |n| is an additional parameter to print on the line, 1
  37.    when you enter a file and 2 when you leave it; normally it is 0 and not
  38.    printed
  39. */
  40. void sync_line(n)
  41.   int n;
  42. {
  43.   switch (sl_style) {
  44.   case SL_NONE:
  45.     break;
  46.   case SL_LINE:
  47.     fprintf(outf, "#line %lu \"%s\"\n", this_line, cur_file);
  48.     break;
  49.   case SL_NORMAL:
  50.     switch (n) {
  51.     case 0:
  52.       fprintf(outf, "# %lu \"%s\"\n", this_line, cur_file);
  53.       break;
  54.     case 1:
  55.     case 2:
  56.       fprintf(outf, "# %lu \"%s\" %d\n", this_line, cur_file, n);
  57.       break;
  58.     default:
  59.       bugchk("can't sync_line(%lu,%d)\n", this_line, n);
  60.       exit(1);
  61.     }
  62.     break;
  63.   }
  64.   last_line = this_line;
  65. }
  66.  
  67. /*
  68.    synchronize() -- synchronize the line number in the output file with the
  69.    input file, either by spitting line feeds or generating a synch line. This
  70.    should not be used if the filename has changed; use sync_line() for that.
  71. */
  72. void synchronize()
  73. {
  74.   if (last_line > this_line || this_line - last_line > MAX_BLANK_LINES)
  75.     sync_line(0);
  76.   else
  77.     for (; last_line < this_line; last_line++)
  78.       fputc('\n', outf);
  79. }
  80.  
  81. /*
  82.    process_line() -- read a line from the input file token by token, doing
  83.    the appropriate thing
  84. */
  85. static int process_line()
  86. {
  87.   register TokenP T;
  88.   register Macro *M;
  89.   register int start_of_line = 1;
  90.  
  91.   for (;;) {
  92.  
  93.     /*
  94.        We must be careful here -- the '#' for a directive cannot come from a
  95.        macro expansion.
  96.     */
  97.     T = (start_of_line ? token(): exp_token());
  98.     if (T->type == EOF_) {
  99.       free_token(T);
  100.       return 0;
  101.     }
  102.     if (T->type == EOL) {
  103.       if (keep_comments) {
  104.     print_token(T);
  105.     last_line++;
  106.       } else if (!start_of_line) {
  107.     fputc('\n', outf);
  108.     last_line++;
  109.       }
  110.       free_token(T);
  111.       if (start_of_line)
  112.     continue;
  113.       else
  114.     break;
  115.     }
  116.     if (start_of_line) {
  117.       /* check for preprocessor directive */
  118.       if (T->type == POUND) {
  119.     free_token(T);
  120.     directive();
  121.     continue;
  122.       }
  123.  
  124.       /*
  125.          If we're in the false branch of an #ifdef and we're not a
  126.          preprocessor directive, just pitch the line and get the next one.
  127.       */
  128.       if (!cond_true()) {
  129.     free_token(T);
  130.     flush_line();
  131.     continue;
  132.       }
  133.  
  134.       /*
  135.          If we get here, we're dealing with a normal line.  We push back the
  136.          token we just read and re-read it with exp_token() to make sure it
  137.          gets expanded.
  138.       */
  139.       if (start_of_line && !in_config_file)
  140.     synchronize();
  141.       start_of_line = 0;
  142.       push_tlist(T);
  143.       T = exp_token();
  144.     }
  145.     print_token(T);
  146.     free_token(T);
  147.   }
  148.   return 1;
  149. }
  150.  
  151. /* path_of_file() -- extract the pathlist from filename |fnam| */
  152. static char *path_of_file(fnam)
  153.   char *fnam;
  154. {
  155.   char *s, *path;
  156.  
  157.   if (!(s = strrchr(fnam, PATH_SEP))) {
  158.     path = mallok(2);
  159.     path[0] = '.';
  160.     path[1] = '\0';
  161.   } else
  162.     path = copy_filename(fnam, (int)(s - fnam));
  163.   return path;
  164. }
  165.  
  166. /*
  167.    save_state() -- save various values particular to the current input file,
  168.    just before opening a new file to process
  169. */
  170. static void save_state(FS)
  171.   register struct file_state *FS;
  172. {
  173.   FS->old_curfile = cur_file;
  174.   FS->old_curdir = I_list[0];
  175.   FS->old_lastline = last_line;
  176.   FS->old_thisline = this_line;
  177.   FS->old_nextline = next_line;
  178.   FS->old_inf = inf;
  179. }
  180.  
  181. /* restore_state() -- restore values saved with save_state() */
  182. static void restore_state(FS)
  183.   register struct file_state *FS;
  184. {
  185.   cur_file = FS->old_curfile;
  186.   I_list[0] = FS->old_curdir;
  187.   last_line = FS->old_lastline;
  188.   this_line = FS->old_thisline;
  189.   next_line = FS->old_nextline;
  190.   inf = FS->old_inf;
  191. }
  192.  
  193. /* process_file() -- open and process file |fnam| */
  194. void process_file(fnam)
  195.   char *fnam;
  196. {
  197.   struct file_state FS;
  198.  
  199.   /* save state values from the previous file */
  200.   save_state(&FS);
  201.   if (streq(fnam, STDIN_NAME))
  202.     inf = stdin;
  203.   else if (!(inf = xfopen(fnam, "r")))
  204.     fatal("cannot open input file %s", fnam);
  205.   cur_file = strdup(fnam);
  206.   I_list[0] = path_of_file(fnam);
  207.   this_line = next_line = 1;
  208.   if (!in_config_file)
  209.     sync_line(1);
  210.   while (process_line()) ;
  211.   if (include_level == 0)
  212.     endif_check();
  213.   if (inf != stdin)
  214.     fclose(inf);
  215.   free(cur_file);
  216.   free(I_list[0]);
  217.   restore_state(&FS);
  218. }
  219.